﻿using DataType;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using DataType.MessageType;
using MapCalclator;
using OprsSimulator.Operators;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OprsSimulator
{
    public class OprsSimulator
    {
        private List<IOperator> operators = new List<IOperator>();

        public List<IOperator> Operators { get => operators; set => operators = value; }

        private List<IOperator> passengers = new List<IOperator>();
        public List<IOperator> Passengers { get => passengers; set => passengers = value; }


        //public void SetObserveDistance(IOperator opr)
        //{
        //    if (typeof(IReconnaissanceAttris).IsAssignableFrom(opr.GetType()) && (Dictionary<OprSubType, int>)opr.GetType().GetProperty("ObserveDistance").GetValue(opr) == null)
        //    {
        //        Dictionary<OprSubType, int> observeDistance = null;
        //        OprType oprType = (OprType)opr.GetType().GetProperty("Type").GetValue(opr);
        //        //车辆、步兵
        //        if (oprType == OprType.Vehicle || oprType == OprType.Infantry)
        //        {
        //            observeDistance = new Dictionary<OprSubType, int>
        //                {
        //                    {OprSubType.Tank, 25},
        //                    {OprSubType.IFV, 25},
        //                    {OprSubType.Infantry, 10},
        //                    {OprSubType.Artillery, 10},
        //                    {OprSubType.UGV, 25},
        //                    {OprSubType.Drone, 1},
        //                    {OprSubType.Helicopter, 25},
        //                    {OprSubType.CruisingMissile, 1},
        //                };
        //            opr.GetType().GetProperty("ObserveDistance").SetValue(opr, observeDistance);
        //        }
        //        //飞机
        //        if (oprType == OprType.Airplane)
        //        {

        //            OprSubType oprSubType = (OprSubType)opr.GetType().GetProperty("Subtype").GetValue(opr);
        //            //无人机、巡飞弹
        //            if (oprSubType == OprSubType.Drone || oprSubType == OprSubType.CruisingMissile)
        //            {
        //                observeDistance = new Dictionary<OprSubType, int>
        //                    {
        //                        {OprSubType.Tank, 2},
        //                        {OprSubType.IFV, 2},
        //                        {OprSubType.Infantry, 2},
        //                        {OprSubType.Artillery, 2},
        //                        {OprSubType.UGV, 2},
        //                        {OprSubType.Drone, 0},
        //                        {OprSubType.Helicopter, 0},
        //                        {OprSubType.CruisingMissile, 0},
        //                    };
        //            }
        //            //直升机
        //            if (oprSubType == OprSubType.Helicopter)
        //            {
        //                observeDistance = new Dictionary<OprSubType, int>
        //                    {
        //                        {OprSubType.Tank, 25},
        //                        {OprSubType.IFV, 25},
        //                        {OprSubType.Infantry, 10},
        //                        {OprSubType.Artillery, 10},
        //                        {OprSubType.UGV, 25},
        //                        {OprSubType.Drone, 1},
        //                        {OprSubType.Helicopter, 25},
        //                        {OprSubType.CruisingMissile, 1},
        //                    };
        //            }
        //            if (observeDistance == null) return;
        //            opr.GetType().GetProperty("ObserveDistance").SetValue(opr, observeDistance);
        //        }
        //    }
        //}
        //public void CompleteAttris()
        //{
        //    for (int i = 0; i < operators.Count; i++)
        //    {
        //        //ObserveDistance无值
        //        SetObserveDistance(operators[i]);
        //    }
        //    for (int i = 0; i < passengers.Count; i++)
        //    {
        //        SetObserveDistance(operators[i]);
        //    }
        //}

        /// <summary>
        /// 根据OnBoard属性，分配算子到operators或者passengers中
        /// </summary>
        public void AssignOperators()
        {
            List<IOperator> operator_oprs = new List<IOperator>();
            List<IOperator> passenger_oprs = new List<IOperator>();
            for (int i = 0; i < operators.Count; i++)
            {
                if ((bool)operators[i].GetType().GetProperty("OnBoard").GetValue(operators[i]))
                {
                    passenger_oprs.Add(operators[i]);
                }
            }
            for (int i = 0; i < passengers.Count; i++)
            {
                if (!(bool)passengers[i].GetType().GetProperty("OnBoard").GetValue(passengers[i]))
                operator_oprs.Add(passengers[i]);
            }

            foreach (IOperator operator_opr in operator_oprs)
            {
                passengers.Remove(operator_opr);
                operators.Add(operator_opr);
            }
            foreach (IOperator passenger_opr in passenger_oprs)
            {
                operators.Remove(passenger_opr);
                passengers.Add(passenger_opr);
            }
        }
        /// <summary>
        /// 根据裁决信息更新operators的独立属性
        /// </summary>
        /// <param name="judgeResults"></param>
        public void UpdateStandalone(List<IJudgeResult> judgeResults, Map map)
        {
            List<IOperator> dead_oprs = new List<IOperator>();
            for (int i = 0; i < operators.Count; i++)
            {
                operators[i].UpdataStandaloneAttris(judgeResults, map);

                if (!typeof(ICommonAttris).IsAssignableFrom(operators[i].GetType())) continue;
                if ((int)operators[i].GetType().GetProperty("Blood").GetValue(operators[i]) <= 0)
                {
                    dead_oprs.Add(operators[i]);
                    //死亡的算子搭载的算子也死亡
                    foreach(IOperator passenger in passengers)
                    {
                        if (operators[i].ObjID == (int)passenger.GetType().GetProperty("Car").GetValue(passenger))
                            dead_oprs.Add(passenger);
                    }
                }             
            }
            foreach(IOperator dead_opr in dead_oprs)
            {
                operators.Remove(dead_opr);
                passengers.Remove(dead_opr);
            }
        }
        public void UpdatePassengers(List<IJudgeResult> judgeResults, List<IOperator> oprs, Map map)
        {
            List<IOperator> dead_oprs = new List<IOperator>();
            for (int i = 0; i < passengers.Count; i++)
            {
                //下车和车辆算子被射击
                passengers[i].UpdataStandaloneAttris(judgeResults, map);

                if (!typeof(ICommonAttris).IsAssignableFrom(passengers[i].GetType())) continue;
                if ((int)passengers[i].GetType().GetProperty("Blood").GetValue(passengers[i]) <= 0)
                {
                    dead_oprs.Add(passengers[i]);
                }
                else passengers[i].UpdateAssociatedAttris(oprs, map);//检测车辆是否被压制
            }
            foreach (IOperator dead_opr in dead_oprs)
            {
                passengers.Remove(dead_opr);
            }
        }

        /// <summary>
        /// 根据更新后的operators属性，更新交互属性
        /// </summary>
        /// <param name="oprs"></param>
        public void UpdateAssociated(List<IOperator> oprs, Map map)
        {
            for (int i = 0; i < operators.Count; i++)
            {
                operators[i].UpdateAssociatedAttris(oprs, map);
            }
        }

        public Dictionary<int, Dictionary<int, List<ActionMsg>>> ConfirmValidActions(List<OperatorMsg> oprs, CityMsg[] cities, Map map, ShootJudgeTable shootJudgeTable)
        {
            Dictionary<int, Dictionary<int, List<ActionMsg>>> valid_actions = new Dictionary<int, Dictionary<int, List<ActionMsg>>>();
            for (int i = 0; i < operators.Count; i++)
            {
                Dictionary<int, List<ActionMsg>> individualValidActions = operators[i].ConfirmValidActions(oprs, cities, map, shootJudgeTable);
                if (valid_actions.ContainsKey(operators[i].ObjID))
                {
                    valid_actions[operators[i].ObjID] = individualValidActions;
                }
                else
                {
                    valid_actions.Add(operators[i].ObjID, individualValidActions);
                }
            }

            return valid_actions;
        }
    }
}
